const SIZE = 10
const MAX_HEIGHT = 100
const $ = sel => document.querySelectorAll(sel)
const DOM = $('.contribution')[0]

let ch_3D = null
let timer = null

// 函数截流.
const throttle = (fn, ctx, arg) => {
  clearTimeout(timer)
  timer = setTimeout(() => fn.call(ctx, arg), 100)
}
// 相邻元素
const siblings = el => [].filter.call(el.parentNode.children, child => child !== el)

const init = () => {
  ch_3D = document.createElement('div')
  ch_3D.id = 'ch_3D'
  ch_3D.className = 'ch_3D_con'
  contentList()
  DOM.appendChild(ch_3D)

  let ch_select = document.createElement('span')
  ch_select.className = 'ch_select'
  ch_select.innerHTML = `<span class="sel" data-sel="contributions_box">2D</span> | <span class="sel" data-sel="ch_3D">3D</span>`
  DOM.querySelector('.contribution-title').appendChild(ch_select)

  binEvent()
}

const binEvent = () => {
  // 当用户更改时间范围 重新计算贡献数据
  document.getElementById('contributions_box').addEventListener('DOMSubtreeModified', () => {
    throttle(() => contentList())
  }, false)

  // 点击更改显示状态
  Array.prototype.forEach.call($('.sel'), el => {
    el.addEventListener('click', () => {
      let id = el.getAttribute('data-sel')
      let view = document.getElementById(id)

      el.classList.add('active')
      siblings(el)[0].classList.remove('active')
      view.style.display = 'block'
      siblings(view)[1].style.display = 'none'

      localStorage.__GITOSC_CH3D__ = id
    }, false)
  })

  // 获取用户习惯
  let loc = localStorage.__GITOSC_CH3D__
  let evt = document.createEvent('HTMLEvents')
  evt.initEvent('click', false, false)
  if (!loc) {
    localStorage.__GITOSC_CH3D__ = 'ch_3D'
    $('.sel[data-sel="ch_3D"]')[0].dispatchEvent(evt)
  } else {
    $('.sel[data-sel="' + loc + '"]')[0].dispatchEvent(evt)
  }
}

// 渲染数据到页面
const contentList = () => {
  let info = fetchData()
  ch_3D.innerHTML = `
	  <div class="ch_stats-right">
	    <div class="ch_stats_row">
	      <span class="title">最近一年贡献</span>
	      <span class="number">${info[0]}</span>
	      <span class="lit">
	        <small class="lit_top">&nbsp;</small>
	        <small class="lit_bottom">次</small>
	      </span>
	    </div>
	    <div class="ch_stats_row">
	      <span class="title">最长连续贡献</span>
	      <span class="number">${info[1]}</span>
	      <span class="lit">
	        <small class="lit_top">&nbsp;</small>
	        <small class="lit_bottom">天</small>
	      </span>
	    </div>
	  </div>

	  <div class="ch_stats-left">
	    <div class="ch_stats_row">
	      <span class="title">最近连续贡献</span>
	      <span class="number">${info[2]}</span>
	      <span class="lit">
	        <small class="lit_top">&nbsp;</small>
	        <small class="lit_bottom">天</small>
	      </span>
	    </div>
	  </div>
	  <canvas id="canvas" width="648" height="420"></canvas>
	`

  let canvas = ch_3D.querySelector('canvas')
  let point = new obelisk.Point(70, 100)
  let pixelView = new obelisk.PixelView(canvas, point)

  Array.prototype.forEach.call($('#contributions_box .vertical'), (ele, i) => {
    if (!i) return;
    Array.prototype.forEach.call(ele.querySelectorAll('.box'), (el, j) => {
      let data = {}
      let con = el.getAttribute('data-content')
      let color = el.className.replace(/box\s/, '').replace(/\s.*/, '')
      let eve, num

      if (con) {
        eve = con.match(/^(\d+)\s+.*\s+(.*)$/)
        num = parseInt(eve[1])
        data.date = eve[2]
        data.h = num < 1 ? 3 : num + 3
      } else {
        data.h = 0
        data.date = 0
      }

      data.x = i
      data.y = j
      data.color = color
      renderData(pixelView, data)
    })
  })
}

const renderData = (pixelView, data) => {
  if (data.h === 0) return;
  let H = data.h <= 5 ? data.h : (data.h - 3) * 2 + 3; //计算高度
  let dimension = new obelisk.CubeDimension(SIZE, SIZE, H < MAX_HEIGHT ? H : MAX_HEIGHT)
  let color = selColor(data.color)
  let cube = new obelisk.Cube(dimension, color, false)
  let p3d = new obelisk.Point3D(data.x * SIZE, data.y * SIZE, 0)
  pixelView.renderObject(cube, p3d)
}

// 获取关键数据 贡献时间，总数等
const fetchData = () => {
  let data = []
  Array.prototype.forEach.call($('#contributions_box .three p'), el => {
    data.push(el.innerHTML.match(/\d+/)[0]);
  })
  return data
}

const selColor = (color) => {
  if (color === 'little') return new obelisk.CubeColor().getByHorizontalColor(0xd6e685);
  if (color === 'some') return new obelisk.CubeColor().getByHorizontalColor(0x8cc665);
  if (color === 'many') return new obelisk.CubeColor().getByHorizontalColor(0x44a340);
  if (color === 'much') return new obelisk.CubeColor().getByHorizontalColor(0x1e6823);
  return new obelisk.CubeColor().getByHorizontalColor(0xeeeeee);
}

if (DOM) {
  init();
  console.log('(❤ v ❤)');
}

if (ENV === 'development') {
  console.log(`[${ENV}] satarted!`)
}
